import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLEncoder;

import org.json.JSONArray; // JSON library from http://www.json.org/java/
import org.json.JSONException;
import org.json.JSONObject;

import java.util.ArrayList;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.FileNotFoundException;
/**
 * Class is heavily based off of:
 * http://frankmccown.blogspot.com/2008/07/yahoos-new-search-boss-api.html
 * 
 * Utilizes JSON in Java (packed in json.jar)
 * http://www.json.org/java/
 * 
 * source courtesy of Douglas Crockford
 * http://www.json.org/java/
 */

/*
 * Yahoo:
 * given a database (url) and query
 * stores the number of total results and an ArrayList of the top 4 URLS returned
 * by Yahoo
 */
public class Yahoo {
    /* ======================================================
     * MEMBERS
     * ====================================================== */
	//number of results to request
	private final int _MAX_RESULTS = 4;
	//number of results received
	private int _num_results = 0;
	//URL obj
	private URL _yahoo_url;

	//category query
	private String _query;
	//app_id
	private ArrayList<String> _query_urls;
	
    /* ======================================================
     * CONSTRUCTORS
     * ====================================================== */
	public Yahoo(String DB, String query, String app_id) {
		this._query = query;
		this._query_urls = new ArrayList<String>();

		//we sleep for a second to cut down on yahoo errors
		try {
			Thread.sleep(1000);
		}
		catch (Exception e) {
			System.out.println("sleep: " + e.getMessage());
		}
		
		String result = getJSON(DB, query, app_id);
		if (result != null) {
			JSONtoURLS(result);
		}
		//printArgs();
	}

	//for cached documents
	public Yahoo(String DB, String query) {
		String url = "cache/urls/" + DB + "/" + query;
		String matches = "cache/matches/" + DB + "/" + query;

		this._query = query;
		this._query_urls = new ArrayList<String>();

		//Queries
		try {
			String str;
			//System.out.println(url);
			BufferedReader in = new BufferedReader(new FileReader(url));
			while ((str = in.readLine()) != null) {
				//System.out.println(str);
				this._query_urls.add(str);
			}
			in.close();

		}catch (Exception e) {
			System.out.println("oops reading cache " + e.getMessage());
			e.printStackTrace();
		}
		

		//num_results
        try {
			String str;
            BufferedReader in = new BufferedReader(new FileReader(matches));
            while ((str = in.readLine()) != null) {
				//System.out.println(str);
				this._num_results = Integer.parseInt(str);
            }
			in.close();
        }catch (Exception e) {
            System.out.println("oops reading cache " + e.getMessage());
        }

	}


    /* ======================================================
     * METHODS
     * ====================================================== */

	public void JSONtoURLS(String yahoo_result) {
		try {
			JSONObject json = new JSONObject(yahoo_result);

			//Get number of results (total hits)
			//this._num_results = Integer.parseInt(json.getJSONObject("ysearchresponse").getString("totalhits"));
			this._num_results = Integer.parseInt(json.getJSONObject("ysearchresponse").getString("totalhits"));
			
			//Get JSON doc object
			JSONArray ja = json.getJSONObject("ysearchresponse").getJSONArray(
					"resultset_web");
			
			for (int i = 0; i < ja.length(); i++) {
				JSONObject j = ja.getJSONObject(i);

				this._query_urls.add(j.getString("url"));

				// System.out.println(j.getString("title"));
				// System.out.println(j.getString("abstract"));
				// System.out.println(j.getString("url"));
			}

		} catch (JSONException e) {
			//System.out.println("Query: " + yahoo_result + " No Results found");
		}

	}
	
	/** 
	 * 
	 * @param args
	 * @return String
	 */
	public String getJSON(String DB, String query, String app_id) {

		String response = null;
		// Encode
		try {

			query = URLEncoder.encode(query, "UTF-8");

			this._yahoo_url = new URL("http://boss.yahooapis.com/ysearch/web/v1/"
					+ query + "?appid=" + app_id //+ "&count=" + this._MAX_RESULTS + 
					+ "&format=json"
					+ "&sites=" + DB
					
					//+ "&filter=-porn&filter=-hate"
					);

			URLConnection connection = _yahoo_url.openConnection();

			String line;
			StringBuilder builder = new StringBuilder();
			BufferedReader reader = new BufferedReader(new InputStreamReader(
					connection.getInputStream()));

			while ((line = reader.readLine()) != null) {
				builder.append(line);
			}

			response = builder.toString();
			//System.out.println(response);

		} catch (Exception e) {
			System.err.println(DB + " " + query + " resulted in Yahoo error: " + e.getMessage());
			//System.out.println(DB + " " + query + " " + "Error in Yahoo Connection");
			//e.printStackTrace();
		}
		return response;
	}
	
	//PrintArgs to print to stdout results of query
	public void printArgs() {
		System.out.println("Parameters");
		System.out.println("Query\t\t = "+ this._query);
		System.out.println("Yahoo URL\t = "+ this._yahoo_url.toString() + "\n");
		System.out.println("Top N Results");
		for (String result : this._query_urls) {
			System.out.println("Result\t\t = " + result);
		}
		System.out.println("Total no of results: " + this._num_results + "\n");
		System.out.println("=====================");
	}
	
	//get total number of hits
	public int get_num_results() {
		return this._num_results;
	}
	//get the list of the 4 urls resulting from a query
	public ArrayList<String> get_query_urls() {
		return this._query_urls;
	}

	/*
	public static void main(String args[]) {
		Yahoo myYahoo = new Yahoo("diabetes.org", "sugar", "pyMB.HbV34HLJ2b2IJeg9L3pSmSgpD7nrVuPrKRtS.S4J_Yu4Edjg4yMZDT2f69CWwF1WpT4Lq_AF8zyKEm9F71RDNIcH7o-");	
	}
	*/
}
